#include "NodoDatos.h"
#include "RegistroDatos.h"


NodoDatos::NodoDatos(){
	this->_proximoNodo = -1;
}

NodoDatos::~NodoDatos(){
	this->_proximoNodo = -1;
}


int NodoDatos::getNextNodo(){
	return this->_proximoNodo;
}

void NodoDatos::setNextNodo(int pos){
	this->_proximoNodo = pos;
}


size_t NodoDatos::serialize(char* &arrBytes){
	this->serInator.reset();

	// Una marca para saber donde empieza el bloque
	char firma = 'D';
	this->serInator.serializar(arrBytes, firma);

	// La cantidad de registros en el bloque
	int cant = this->lRegistros.size();
	this->serInator.serializar(arrBytes, cant);

	// Uno a uno serializa los registros
	std::list<IRegistro*>::iterator it;
	for (it = this->lRegistros.begin(); it != this->lRegistros.end(); ++it){
		this->serInator.serializar(arrBytes, *it);
	}
	
	// El puntero al proximo nodo
	this->serInator.serializar(arrBytes, this->_proximoNodo);

	return sizeof(firma) + sizeof(this->lRegistros.size()) +
			this->serInator.getBufferSize() + sizeof(this->_proximoNodo);
}


void NodoDatos::deSerialize(char* arrBytes){
	// Primero limpia el nodo por si tiene algun dato y luego
	// inicializa el serializador
	this->clear();
	this->serInator.reset();

	// Una marca para saber donde empieza el bloque
	char firma = 'D';
	this->serInator.desSerializar(arrBytes, firma);

	// La cantidad de registros en el bloque
	int cantElementos = 0;
	this->serInator.desSerializar(arrBytes, cantElementos);

	// Los elementos del Nodo
	for (int i=0; i< cantElementos; ++i){
		// Un nodo de datos siempre contiene registros de datos
		IRegistro* regTemp = new RegistroDatos();

		this->serInator.desSerializar(arrBytes, regTemp);
		this->lRegistros.push_back(regTemp);
	}

	// El puntero al proximo nodo
	this->serInator.desSerializar(arrBytes, this->_proximoNodo);
}


size_t NodoDatos::getSize() const{
	size_t tamDatos = this->getBytes();

	// Mas el tamaño de los metadatos
	size_t tamMeta = sizeof(char); // La marca de debug
	tamMeta += sizeof(int);	// El contador de elementos
	tamMeta += sizeof(this->_proximoNodo);

	return tamDatos + tamMeta;
}


// Devuelve un nuevo registro con el separador entre este nodo y el nodo "n"
IRegistro& NodoDatos::construirRegistroDivisor(INodo& n){

	/** En este caso el separador entre dos nodos de datos es la menor clave
	 * del nodo de la derecha o nodo hermano mayor; este seria el nodo "n"
	 * */

	// El maximo valor de este nodo es el ultimo registro
	std::list<IRegistro*>::const_reverse_iterator itMax = this->lRegistros.rbegin();

	// El máximo de este nodo es menor estricto que el minimo de la derecha
	// TODO: No me gusta esto, tiene que haber una mejor manera
	RegistroDatos reg = n.buscarRegistroPorId(**itMax, false);
	IRegistro* reg2 = new RegistroDatos(reg.getClave(), reg.getDato());

	// Devuelve una copia del registro
	return *reg2;
}
